package br.com.locasis.funcionalidades;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Out;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.international.StatusMessage.Severity;
import org.jboss.seam.international.StatusMessages;

import br.com.locasis.entity.Agendamento;
import br.com.locasis.entity.Automovel;
import br.com.locasis.entity.Cliente;
import br.com.locasis.entity.Usuario;

@Name("cadastrarAgenda")
@Scope(ScopeType.CONVERSATION)
//@Restrict(value="#{identity.hasRole('"+PerfilUsuario.PERFIL_PETSHOP+"')}")
public class CadastrarAgenda {
	
	@In(create=true)
	private EntityManager entityManager;
	
	@In(required = false)
    Usuario usuarioLogado;
	
	@In(value = "statusMessages")
	protected StatusMessages messages;
	
	private Agendamento agendamentoEdicao;
	
	/**
	 * remover este atributo
	 */
	@Deprecated
	private Date dataAgendamento;
	
	private Date dataInicial;
	
	private Date dataFinal;
	
	private Automovel automovelPesquisa;
	
	private List<Agendamento> listaAgendamentos;
	
	private List<Automovel> listaAutomoveis;
	
	private Automovel automovelSelecionado;
	
	private Cliente clientePesquisa;
	
	private Cliente clienteSelecionado;
	
	private List<Cliente> listaClientes;
	
	private Integer horaInicio;
	
	private Integer minutoInicio;
	
	private Integer horaFim;
	
	private Integer minutoFim;
	
	@Out(required=false)
	private Agendamento agendamentoSelecionado;
	
	public Cliente getClientePesquisa() {
		if (clientePesquisa == null) {
			clientePesquisa = new Cliente();
		}
		return clientePesquisa;
	}

	public void setClientePesquisa(Cliente clientePesquisa) {
		this.clientePesquisa = clientePesquisa;
	}

	public Cliente getClienteSelecionado() {
		return clienteSelecionado;
	}

	public void setClienteSelecionado(Cliente clienteSelecionado) {
		this.clienteSelecionado = clienteSelecionado;
	}

	public List<Cliente> getListaClientes() {
		if (listaClientes == null) {
			listaClientes = new ArrayList<Cliente>();
		}
		return listaClientes;
	}

	public void setListaClientes(List<Cliente> listaClientes) {
		this.listaClientes = listaClientes;
	}

	public Integer getHoraInicio() {
		return horaInicio;
	}

	public void setHoraInicio(Integer horaInicio) {
		this.horaInicio = horaInicio;
	}

	public Integer getMinutoInicio() {
		return minutoInicio;
	}

	public void setMinutoInicio(Integer minutoInicio) {
		this.minutoInicio = minutoInicio;
	}

	public Integer getHoraFim() {
		return horaFim;
	}

	public void setHoraFim(Integer horaFim) {
		this.horaFim = horaFim;
	}

	public Integer getMinutoFim() {
		return minutoFim;
	}

	public void setMinutoFim(Integer minutoFim) {
		this.minutoFim = minutoFim;
	}

	public Automovel getAutomovelSelecionado() {
		return automovelSelecionado;
	}

	public void setAutomovelSelecionado(Automovel automovelSelecionado) {
		this.automovelSelecionado = automovelSelecionado;
	}

	private boolean selecionadoTodos;
	
	public Automovel getAutomovelPesquisa() {
		if (automovelPesquisa == null) {
			automovelPesquisa = new Automovel();
		}
		return automovelPesquisa;
	}

	public void setAutomovelPesquisa(Automovel automovelPesquisa) {
		this.automovelPesquisa = automovelPesquisa;
	}
	
	public List<Automovel> getListaAutomoveis() {
		if (listaAutomoveis == null) {
			listaAutomoveis = new ArrayList<Automovel>();
		}
		return listaAutomoveis;
	}

	public void setListaAutomoveis(List<Automovel> listaAutomoveis) {
		this.listaAutomoveis = listaAutomoveis;
	}

	public boolean isSelecionadoTodos() {
		return selecionadoTodos;
	}

	public Date getDataAgendamento() {
		return dataAgendamento;
	}

	public void setDataAgendamento(Date dataAgendamento) {
		this.dataAgendamento = dataAgendamento;
	}

	public Date getDataInicial() {
		return dataInicial;
	}

	public void setDataInicial(Date dataInicial) {
		this.dataInicial = dataInicial;
	}

	public Date getDataFinal() {
		return dataFinal;
	}

	public void setDataFinal(Date dataFinal) {
		this.dataFinal = dataFinal;
	}

	public void setSelecionadoTodos(boolean selecionadoTodos) {
		this.selecionadoTodos = selecionadoTodos;
	}
	
	public Agendamento getAgendamentoEdicao() {
		if (agendamentoEdicao == null) {
			agendamentoEdicao = new Agendamento();
		}
		return agendamentoEdicao;
	}

	public void setAgendamentoEdicao(Agendamento agendamentoEdicao) {
		this.agendamentoEdicao = agendamentoEdicao;
	}

	public List<Agendamento> getListaAgendamentos() {
		if (listaAgendamentos == null) {
			listaAgendamentos = new ArrayList<Agendamento>();
		}
		return listaAgendamentos;
	}

	public void setListaAgendamentos(List<Agendamento> listaAgendamentos) {
		this.listaAgendamentos = listaAgendamentos;
	}

	public Agendamento getAgendamentoSelecionado() {
		return agendamentoSelecionado;
	}

	public void setAgendamentoSelecionado(Agendamento agendamentoSelecionado) {
		this.agendamentoSelecionado = agendamentoSelecionado;
	}
	
	public void pesquisaClientes(){
		StringBuffer query = new StringBuffer("select c from Cliente c where c.flgAtivo is true ");
		if(getClientePesquisa().getNome() != null &&
				!getClientePesquisa().getNome().isEmpty()){
			query.append(" and UPPER(c.nome) like UPPER(:nome)");
		}
		if(getClientePesquisa().getCpf() != null &&
				!getClientePesquisa().getCpf().isEmpty()){
			query.append(" and c.cpf = :cpf");
		}
		if(getClientePesquisa().getPassaporte() != null &&
				!getClientePesquisa().getPassaporte().isEmpty()){
			query.append(" and c.passaporte = :passaporte");
		}
		if(getClientePesquisa().getNroCartaoGold() != null &&
				!getClientePesquisa().getNroCartaoGold().isEmpty()){
			query.append(" and c.nroCartaoGold = :nroCartao");
		}
		
		Query qryResult = entityManager.createQuery(query.toString());
		
		if(getClientePesquisa().getNome() != null &&
				!getClientePesquisa().getNome().isEmpty()){
			qryResult.setParameter("nome", "%"+getClientePesquisa().getNome()+"%");
		}
		if(getClientePesquisa().getCpf() != null &&
				!getClientePesquisa().getCpf().isEmpty()){
			qryResult.setParameter("cpf", getClientePesquisa().getCpf());
		}
		if(getClientePesquisa().getPassaporte() != null &&
				!getClientePesquisa().getPassaporte().isEmpty()){
			qryResult.setParameter("passaporte", getClientePesquisa().getPassaporte());
			query.append(" and c.passaporte = :passaporte");
		}
		if(getClientePesquisa().getNroCartaoGold() != null &&
				!getClientePesquisa().getNroCartaoGold().isEmpty()){
			qryResult.setParameter("nroCartao", getClientePesquisa().getNroCartaoGold());
			query.append(" and c.nroCartaoGold = :nroCartao");
		}
		
		listaClientes = qryResult.getResultList();
	}

	
	public void pesquisaAutomoveis(){
		StringBuffer query = new StringBuffer("select a from Automovel a where a.flgAtivo is true ");
		if(getAutomovelPesquisa().getMarca() != null &&
				!getAutomovelPesquisa().getMarca().isEmpty()){
			query.append("and UPPER(a.marca) = UPPER(:marca)");
		}
		if(getAutomovelPesquisa().getModelo() != null &&
				!getAutomovelPesquisa().getModelo().isEmpty()){
			query.append("and UPPER(a.modelo) = UPPER(:modelo)");
		}
		if(getAutomovelPesquisa().getPlaca() != null &&
				!getAutomovelPesquisa().getPlaca().isEmpty()){
			query.append("and UPPER(a.placa) = UPPER(:placa)");
		}
		if(getAutomovelPesquisa().getCor() != null &&
				!getAutomovelPesquisa().getCor().isEmpty()){
			query.append("and UPPER(a.cor) = UPPER(:cor)");
		}
		if(getAutomovelPesquisa().getChassi() != null &&
				!getAutomovelPesquisa().getChassi().isEmpty()){
			query.append("and UPPER(a.chassi) = UPPER(:chassi)");
		}
		if(getAutomovelPesquisa().getAnoModelo() != null){
			query.append("and UPPER(a.anoModelo) = UPPER(:anoModelo)");
		}
		if(getAutomovelPesquisa().getAnoFabricacao() != null){
			query.append("and UPPER(a.anoFabricacao) = UPPER(:anoFabricacao)");
		}
		
		Query qryResult = entityManager.createQuery(query.toString());
		
		if(getAutomovelPesquisa().getMarca() != null &&
				!getAutomovelPesquisa().getMarca().isEmpty()){
			qryResult.setParameter("marca", "%"+getAutomovelPesquisa().getMarca()+"%");
		}
		if(getAutomovelPesquisa().getModelo() != null &&
				!getAutomovelPesquisa().getModelo().isEmpty()){
			qryResult.setParameter("modelo", "%"+getAutomovelPesquisa().getModelo()+"%");
		}
		if(getAutomovelPesquisa().getPlaca() != null &&
				!getAutomovelPesquisa().getPlaca().isEmpty()){
			qryResult.setParameter("placa", getAutomovelPesquisa().getPlaca());
		}
		if(getAutomovelPesquisa().getCor() != null &&
				!getAutomovelPesquisa().getCor().isEmpty()){
			qryResult.setParameter("cor", getAutomovelPesquisa().getCor());
		}
		if(getAutomovelPesquisa().getChassi() != null &&
				!getAutomovelPesquisa().getChassi().isEmpty()){
			qryResult.setParameter("chassi", getAutomovelPesquisa().getChassi());
		}
		if(getAutomovelPesquisa().getAnoModelo() != null){
			qryResult.setParameter("anoModelo", getAutomovelPesquisa().getAnoModelo());
		}
		if(getAutomovelPesquisa().getAnoFabricacao() != null){
			qryResult.setParameter("anoFabricacao", getAutomovelPesquisa().getAnoFabricacao());
		}
		
		listaAutomoveis = qryResult.getResultList();
	}
	
	public void pesquisar(){
		/*if(getDataAgendamento() == null){
			messages.add(Severity.WARN,"Selecione uma data no calendário.");
			return;
		}*/
		StringBuffer query = new StringBuffer("select a from Agendamento a where a.flgAtivo is true");
		
		/*
		if(getDataAgendamento() != null){
			query.append(" and DATE(a.dataInicio) = DATE(:data)");
		}
		*/
		if (getDataInicial() != null) {
			query.append(" and DATE(a.dataInicio ) >= DATE(:dataInicial) ");
		}
		if (getDataFinal() != null) {
			query.append(" and DATE(a.dataFim ) <= DATE(:dataFinal) ");
		}
		
		query.append(" order by a.dataInicio");
		
		Query qryResult = entityManager.createQuery(query.toString());
		/*
		if (getDataAgendamento() != null){
			qryResult.setParameter("dataInicial", getDataAgendamento());
		}
		*/
		if (getDataInicial() != null){
			qryResult.setParameter("dataInicial", getDataInicial());
		}
		
		if (getDataFinal() != null) {
			qryResult.setParameter("dataFinal", getDataFinal());
		}
		
		listaAgendamentos = qryResult.getResultList();
		
		if(listaAgendamentos == null || listaAgendamentos.size() == 0){
			messages.add(Severity.WARN,"Nenhum registro encontrado.");
		}
	}

	public void selecionaTodos(){
		for(Agendamento a : getListaAgendamentos()){
			if(isSelecionadoTodos()){
				a.setSelecionado(true);
			}else{
				a.setSelecionado(false);
			}
		}
	}

	public void onLoad(){
		setListaAgendamentos(null);
		if(agendamentoSelecionado != null){
			agendamentoEdicao = agendamentoSelecionado;
		}
	}
	
	public void onLoadList(){
		setAgendamentoEdicao(null);
		setAutomovelSelecionado(null);
		setListaAutomoveis(null);
		setAutomovelPesquisa(null);
		setHoraInicio(null);
		setMinutoInicio(null);
		setHoraFim(null);
		setMinutoFim(null);
		agendamentoSelecionado = null;
	}
	
	public boolean validarDisponibilidadeData(Date dataInicio, Date dataFim, Automovel automovel){
		
		List<Agendamento> retorno = entityManager.createQuery("select a from Agendamento a where a.dataInicio <= :data and a.dataFim >= :data and a.automovel.idAutomovel = :idAutomovel and a.flgAtivo is true")
			.setParameter("data", dataInicio)
			.setParameter("idAutomovel", automovel.getIdAutomovel())
			.getResultList();
		
		if(retorno == null || retorno.size() == 0){
			retorno = entityManager.createQuery("select a from Agendamento a where a.dataInicio <= :data and a.dataFim >= :data and a.automovel.idAutomovel = :idAutomovel and a.flgAtivo is true")
				.setParameter("data", dataFim)
				.setParameter("idAutomovel", automovel.getIdAutomovel())
				.getResultList();
			if(retorno == null || retorno.size() == 0){
				return true;
			}
		}
		return false;
	}
	
	public boolean validarDisponibilidadeDataEdicao(Date dataInicio, Date dataFim, Automovel automovel, Integer idAgendamento){
		
		List<Agendamento> retorno = entityManager.createQuery("select a from Agendamento a where a.dataInicio <= :data and a.dataFim >= :data and a.automovel.idAutomovel = :idAutomovel and a.flgAtivo is true and a.idAgendamento <> :idAgendamento")
		.setParameter("data", dataInicio)
		.setParameter("idAutomovel", automovel.getIdAutomovel())
		.setParameter("idAgendamento", idAgendamento)
		.getResultList();
		
		if(retorno == null || retorno.size() == 0){
			retorno = entityManager.createQuery("select a from Agendamento a where a.dataInicio <= :data and a.dataFim >= :data and a.automovel.idAutomovel = :idAutomovel and a.flgAtivo is true and a.idAgendamento <> :idAgendamento")
			.setParameter("data", dataFim)
			.setParameter("idAutomovel", automovel.getIdAutomovel())
			.setParameter("idAgendamento", idAgendamento)
			.getResultList();
			if(retorno == null || retorno.size() == 0){
				return true;
			}
		}
		return false;
	}

	public String salvar(){
		if(getAutomovelSelecionado() == null){
			messages.add(Severity.ERROR,"O campo Veículo é de preenchimento obrigatório.");
			return null;
		}
		
		if(getClienteSelecionado() == null){
			messages.add(Severity.ERROR,"O campo Cliente é de preenchimento obrigatório.");
			return null;
		}
		
		Calendar dataInicio = Calendar.getInstance();
		dataInicio.setTime(getAgendamentoEdicao().getDataInicio());
		dataInicio.set(Calendar.HOUR, getHoraInicio());
		dataInicio.set(Calendar.MINUTE, getMinutoInicio());
		
		Calendar dataFim = Calendar.getInstance();
		dataFim.setTime(getAgendamentoEdicao().getDataFim());
		dataFim.set(Calendar.HOUR, getHoraFim());
		dataFim.set(Calendar.MINUTE, getMinutoFim());
		
		boolean valido;
		if(getAgendamentoEdicao().getIdAgendamento() == null){
			getAgendamentoEdicao().setUsuario(this.usuarioLogado);
			valido = validarDisponibilidadeData(dataInicio.getTime(), dataFim.getTime(), getAutomovelSelecionado());
		}else{
			valido = validarDisponibilidadeDataEdicao(dataInicio.getTime(), dataFim.getTime(), getAutomovelSelecionado(), getAgendamentoEdicao().getIdAgendamento());
		}
		if(valido){
			getAgendamentoEdicao().setDataInicio(dataInicio.getTime());
			getAgendamentoEdicao().setDataFim(dataFim.getTime());
			getAgendamentoEdicao().setAutomovel(getAutomovelSelecionado());
			getAgendamentoEdicao().setCliente(getClienteSelecionado());
			getAgendamentoEdicao().setFlgAtivo(true);
			entityManager.merge(getAgendamentoEdicao());
			entityManager.flush();
			messages.add(Severity.INFO,"Agendamento cadastrado com sucesso.");
			setAgendamentoEdicao(null);
			return "persisted";
		}else{
			messages.add(Severity.ERROR,"Já existe um agendamento cadastrado para essa data e veículo.");
		}
		return null;
	}
	
	public void selecionarAutomovel(Automovel automovel){
		automovelSelecionado = automovel;
	}
	
	public void selecionarCliente(Cliente cliente){
		clienteSelecionado = cliente;
	}
	
	public String cancelar(){
		setAgendamentoEdicao(null);
		return "voltar";
	}
	
	public void excluir(){
		List<Agendamento> listaRemocao = new ArrayList<Agendamento>();
		for(Agendamento a : getListaAgendamentos()){
			if(a.isSelecionado()){
				a.setFlgAtivo(false);
				entityManager.merge(a);
				listaRemocao.add(a);
			}
		}
		getListaAgendamentos().removeAll(listaRemocao);
		entityManager.flush();
		messages.add(Severity.INFO,"Agendamento(s) excluído(s) com sucesso.");
	}
	
	public String novo(){
		return "novo";
	}
	
	public String editar(Agendamento agendamento){
		agendamentoSelecionado = agendamento;
		automovelSelecionado = agendamento.getAutomovel();
		clienteSelecionado = agendamento.getCliente();
		Calendar dataInicio = Calendar.getInstance();
		dataInicio.setTime(agendamento.getDataInicio());
		setHoraInicio(dataInicio.get(Calendar.HOUR));
		setMinutoInicio(dataInicio.get(Calendar.MINUTE));
		
		Calendar dataFim = Calendar.getInstance();
		dataFim.setTime(agendamento.getDataFim());
		setHoraFim(dataFim.get(Calendar.HOUR));
		setMinutoFim(dataFim.get(Calendar.MINUTE));
		return "editar";
	}
}
